import { forTitle } from '$utils/forTitle';
import { getPersistent, setPersistent } from '$utils/getPersistent';
import alova from '$utils/request';
import { onDestroy, onMount } from 'svelte';
import { get, writable } from 'svelte/store';
// import type { AlovaReq } from './types';

export type ReqParam = string | ((params?: IObject) => Promise<IObject>);

export type InitOptions = {
	persist?: string;
	callback?: (res: IObject) => void;
	type?: 'get' | 'post';
	isInit: boolean;
	loadingInitial?: boolean;
	params?: IObject; // 请求参数
	handle?: (res: IObject, initList: (list?: IObject | IObject[]) => void) => void;
};

export function mergeOptions<T = IObject>(options: T, params: T) {
	Object.keys(params as IObject).forEach((key) => {
		if (options[key] === undefined) {
			options[key] = params[key];
		}
	});
}

export function useCommonPageInit<T = Product.ProductDetail, K = IObject>(
	req: ReqParam,
	options: InitOptions
) {
	const defaultOptions: InitOptions = { isInit: true, loadingInitial: false, type: 'get' }; // 默认初始化
	mergeOptions(options, defaultOptions);

	const controller = new AbortController();
	const list = writable<T[]>([]);
	const pageData = writable<K>({} as IObject);
	const loading = writable<boolean>(options.loadingInitial);
	const error = writable<string | number>('');

	const errCallback = (err: string | number = '') => {
		loading.set(false);
		error.set(err);
	};

	const initList = (listData) => {
		if ((listData as IObject | IObject[]).length >= 0) {
			list.set(listData);
		} else {
			pageData.set(listData as IObject);
		}
	};

	const query = async () => {
		loading.set(true);
		if (options.persist) {
			const data = getPersistent<IObject | IObject[]>(options.persist);
			if (data)
				return (
					options.handle!(data as IObject, initList), loading.set(false), Promise.resolve(data)
				);
		}

		return new Promise((resolve) => {
			if (typeof req === 'string') {
				alova[forTitle(options.type)]<IObject>(req, options.params, { signal: controller.signal })
					.then((res) => {
						if (res.code === 500 || res.code === 404) return errCallback(res.code);
						if (res.code === 504) return errCallback(res.code);
						if (options.callback) options.callback(res.data);
						resolve(res.data);
					})
					.catch(() => errCallback());
			} else {
				req(options.params)
					.then((res) => {
						if (res.code === 500 || res.code === 404) return errCallback(res.code);
						if (options.callback) options.callback(res.data);
						resolve(res.data);
					})
					.catch(() => errCallback());
			}
		}).then((data) => {
			loading.set(false);
			if (options.handle) options.handle(data as IObject, initList);
			if (options.persist) setPersistent(options.persist, data);
		});
	};

	if (options.isInit) {
		onMount(() => {
			query();
		});
	}

	onDestroy(() => {
		controller.abort();
	});

	return { list, pageData, loading, error, query, options };
}
